package com.autumn.zero.workflow.configure;

import java.io.IOException;

import javax.sql.DataSource;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.autumn.zero.workflow.application.services.IWorkflowFormAppService;
import com.autumn.zero.workflow.application.services.impl.WorkflowFormAppServiceImpl;
import com.autumn.zero.workflow.listeners.IProcessListenerNotify;
import com.autumn.zero.workflow.listeners.ProcessListenerNotifyManager;
import com.autumn.zero.workflow.services.IListenerService;
import com.autumn.zero.workflow.services.impl.ListenerServiceImpl;

/**
 * 工作流配置
 * 
 * @author 杨昌国 2018-12-19 12:37:46
 */
@Configuration
public class AutumnBaseZeroWorkflowConfiguration {

	/**
	 * 日志
	 */
	private final Log logger = LogFactory.getLog(AutumnBaseZeroWorkflowConfiguration.class);

	@Bean
	@ConditionalOnMissingBean(ProcessEngine.class)
	public ProcessEngine activitiProcessEngine(DataSourceTransactionManager transactionManager, DataSource dataSource)
			throws IOException {
		SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
		try {
			String bpmnPath = ResourceLoader.CLASSPATH_URL_PREFIX + "processes/*.bpmn";
			Resource[] resources = new PathMatchingResourcePatternResolver().getResources(bpmnPath);
			if (resources != null) {
				configuration.setDeploymentResources(resources);
			}
		} catch (Exception e) {
			logger.info("未能在 processes 路径下发现任何 bpmn 文件。");
		}
		configuration.setTransactionManager(transactionManager);
		configuration.setDataSource(dataSource);
		configuration.setDatabaseSchemaUpdate("true");
		configuration.setDbIdentityUsed(false);
		return configuration.buildProcessEngine();
	}

	@Bean
	@ConditionalOnMissingBean(RepositoryService.class)
	public RepositoryService activitiRepositoryService(ProcessEngine processEngine) {
		return processEngine.getRepositoryService();
	}

	@Bean
	@ConditionalOnMissingBean(RuntimeService.class)
	public RuntimeService activitiRuntimeService(ProcessEngine processEngine) {
		return processEngine.getRuntimeService();
	}

	@Bean
	@ConditionalOnMissingBean(TaskService.class)
	public TaskService activitiTaskService(ProcessEngine processEngine) {
		return processEngine.getTaskService();
	}

	@Bean
	@ConditionalOnMissingBean(HistoryService.class)
	public HistoryService activitiHistoryService(ProcessEngine processEngine) {
		return processEngine.getHistoryService();
	}

	@Bean
	@ConditionalOnMissingBean(ManagementService.class)
	public ManagementService activitiManagementService(ProcessEngine processEngine) {
		return processEngine.getManagementService();
	}

	@Bean
	@ConditionalOnMissingBean(IdentityService.class)
	public IdentityService activitiIdentityService(ProcessEngine processEngine) {
		return processEngine.getIdentityService();
	}

	/**
	 * 工作流表单应用服务
	 * 
	 * @return
	 */
	@Bean
	@ConditionalOnMissingBean(IWorkflowFormAppService.class)
	public IWorkflowFormAppService autumnZeroWorkflowFormAppService() {
		return new WorkflowFormAppServiceImpl();
	}

	/**
	 * 工作流表单应用服务
	 * 
	 * @return
	 */
	@Bean
	@ConditionalOnMissingBean(IListenerService.class)
	public IListenerService autumnZeroListenerService() {
		return new ListenerServiceImpl();
	}

	/**
	 * 进程监听通知管理
	 * 
	 * @return
	 */
	@Bean
	@ConditionalOnMissingBean(ProcessListenerNotifyManager.class)
	public ProcessListenerNotifyManager autumnZeroProcessListenerNotifyManager() {
		return new ProcessListenerNotifyManager();
	}

	/**
	 * 进程通知拦截
	 * 
	 * @param processListenerNotifyManager
	 * @return
	 */
	@Bean
	public BeanPostProcessor autumnProcessListenerNotifyBeanPostProcessor(
			ProcessListenerNotifyManager processListenerNotifyManager) {
		processListenerNotifyManager.initialize();
		return new BeanPostProcessor() {
			@Override
			public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
				if (bean instanceof IProcessListenerNotify) {
					IProcessListenerNotify processListener = (IProcessListenerNotify) bean;
					processListenerNotifyManager.register(processListener);
				}
				return bean;
			}

			@Override
			public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
				return bean;
			}
		};
	}

}
